//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//
//  Copyright 2015 Autodesk, Inc.  All rights reserved.
//
//  Use of this software is subject to the terms of the Autodesk license 
//  agreement provided at the time of installation or download, or which 
//  otherwise accompanies this software in either electronic or hard copy form.   
//
//////////////////////////////////////////////////////////////////////////////

#pragma once 

#include "AcDbPointCloudEx.h"
#include "AcPointCloudExtractProfileCurve.h"

/// <summary>
/// Option to do point cloud line extraction
/// </summary>
///
class ACDB_PORT ExtractOption
{
public:
    /// <summary>
    /// Extraction type, outline or floorplan
    /// </summary>
    ///
    enum ExtractionType
    {
        kOutLine,
        kAllLine,
    };

public:
    /// <summary>
    /// Extract type, out line or floorplan.
    /// </summary>
    ///
    ExtractionType  m_extractionType;
    /// <summary>
    /// Maxium points to process. it should be bigger than 0.
    /// Usually 5000 -2000000 is reasonable.
    /// </summary>
    ///
    unsigned int    m_processPoints;
    /// <summary>
    /// Collect line tolerance. It should be bigger than 0.
    /// </summary>
    ///
    double          m_fillGap;
    /// <summary>
    /// Collect line within this angle if distance is within fillgap.
    /// Usually 0-10 is reasonable.
    /// </summary>
    ///
    unsigned int    m_snapAngle;
    /// <summary>
    /// Minium segment length. It should be bigger than 0.
    /// </summary>
    ///
    double          m_minSegLength;
    /// <summary>
    /// If use line segments only or include arcs
    /// </summary>
    ///
    bool            m_useLineSegmentOnly;

    ExtractOption();
};

/// <summary>
/// Point cloud line extraction process callback
/// </summary>
///
class ACDB_PORT IPointCloudExtracProgressCallback
{
public:
    IPointCloudExtracProgressCallback(void){}
    virtual ~IPointCloudExtracProgressCallback(void){}

    /// <summary>
    /// Update progressing, from 0 ~ 99.    
    /// </summary>
    ///
    virtual void updateProgress(int progress) = 0;

    /// <summary>
    /// Update caption displayed in the progress dialog if there's any
    /// </summary>
    ///
    virtual void updateCaption(const AcString& caption) = 0;

    /// <summary>
    /// Whether or not the callback is cancelled.
    /// return true if cancelled.
    /// </summary>
    ///
    virtual bool cancelled() const = 0;

    /// <summary>
    /// Cancel the progress.
    /// </summary>
    ///
    virtual void cancel() = 0;

    /// <summary>
    /// Update the remaining time of the progress. In seconds.
    /// </summary>
    ///
    virtual void updateRemainTime(double remainTime) = 0;

    /// <summary>
    /// End the process.
    /// </summary>
    ///
    virtual void end() = 0;
};

/// <summary>
/// Utility class to do point cloud line extraction and line output.
/// </summary>
///
class ACDB_PORT AcPointCloudExtractor 
{
public:

    /// <summary>
    /// Extract point cloud in a plane and give result.
    /// </summary>
    /// <param name="pointCloud">The pointcloud to be extracted.</param>
    /// <param name="planeZDirection">Z direction of extraction plan, in drawing space.</param>
    /// <param name="planeXDirection">X direction of extraction plan, in drawing space.</param>
    /// <param name="pointPlane">A point on extraction plan.</param>
    /// <param name="extractOption">Extract option.</param>
    /// <param name="outlineResult">Out line result.</param>
    /// <param name="progress">The call back function for the progress.</param>
    /// <return> Return Acad::eOk if success, otherwise return Acad::eNotApplicable.</return>
    ///
    static Acad::ErrorStatus extract(AcDbPointCloudEx *pointCloud,
        const AcGeVector3d& planeZDirection,
        const AcGeVector3d& planeXDirection,
        const AcGePoint3d pointPlane,
        const ExtractOption& extractOption,
        AcPointCloudExtractResult& outlineResult,
        IPointCloudExtracProgressCallback* progress = 0);
    
    /// <summary>
    /// append line from extraction result.
    /// <return> Return the line's object ids appended.</return>
    /// </summary>
    /// <param name="profile">The extracted line result generated by extract method. The lines are 2d and in ecs size.</param>
    /// <param name="spaceId">The work space id you want to add the linework.</param>
    /// <param name="layer">The layer you want to add the linework.</param>
    /// <param name="color">The color you want set for the linework.</param>
    /// <return> Return the object ids for the linework.</return>
    ///
    static AcDbObjectIdArray appendLineProfile(const AcPointCloudExtractResult& profile,
        AcDbObjectId spaceId,
        AcString layer,
        AcCmColor color);

    /// <summary>
    /// append poly line from extraction result.
    /// <return> Return the pline's object ids appended.</return>
    /// </summary>
    /// <param name="profile">The extracted line result generated by extract method. The lines are 2d and in ecs size.</param>
    /// <param name="spaceId">The work space id you want to add the plines.</param>
    /// <param name="layer">The layer you want to add the plines.</param>
    /// <param name="color">The color you want set for the plines.</param>
    /// <return> Return the object ids for the plines.</return>
    ///
    static AcDbObjectIdArray appendPolylineProfile(const AcPointCloudExtractResult& profile,
        AcDbObjectId spaceId,
        AcString layer,
        AcCmColor color,
        double polylineWidth);

};
